﻿using System.Security.Authentication;
using EdgeTTS.Net.Models;
using WebSocketSharp;
using LogLevel = EdgeTTS.Net.Models.LogLevel;

namespace EdgeTTS.Net;

[Flags]
public enum SslProtocolsHack
{
    Tls = 192,
    Tls11 = 768,
    Tls12 = 3072
}

public class Wss
{
    private readonly WebSocket _wss;

    public Wss(string url)
    {
        try
        {
            _wss = new WebSocket(url);
            const SslProtocols sslProtocolHack = (SslProtocols)(SslProtocolsHack.Tls12 | SslProtocolsHack.Tls11 | SslProtocolsHack.Tls);
            _wss.SslConfiguration.EnabledSslProtocols = sslProtocolHack;
            if (url.Contains("wss://"))
                _wss.SslConfiguration.ServerCertificateValidationCallback =
                    (sender, certificate, chain, sslPolicyErrors) => true;
            _wss.OnOpen += (sender, e) => { OnLog?.Invoke(new Log(LogLevel.Info, "WebSocket Open")); };
            _wss.OnMessage += (sender, e) => OnMessage?.Invoke(sender, e);
            _wss.OnClose += (sender, e) =>
            {
                //TlsHandshakeFailure
                if (e.Code == 1015 && _wss.SslConfiguration.EnabledSslProtocols != sslProtocolHack)
                {
                    OnLog?.Invoke(new Log(LogLevel.Error, "ssl握手失败，正在尝试重新连接."));
                    _wss.SslConfiguration.EnabledSslProtocols = sslProtocolHack;
                    _wss.Connect();
                }
                else
                {
                    OnClose?.Invoke(sender, e);
                }
            };
        }
        catch (Exception e)
        {
            OnLog?.Invoke(new Log(LogLevel.Error, $"WebSocket Exception:{e}"));
            throw;
        }
    }

    public event Action<Log>? OnLog;
    public event EventHandler<MessageEventArgs>? OnMessage;
    public event EventHandler<CloseEventArgs>? OnClose;

    public bool Run()
    {
        _wss.Connect();
        if (_wss.IsAlive)
            OnLog?.Invoke(new Log(LogLevel.Info, "WebSocket 连接成功."));
        if (_wss.IsSecure)
            OnLog?.Invoke(new Log(LogLevel.Info, "WebSocket 是安全的."));
        return _wss.IsAlive;
    }

    public void Close()
    {
        _wss.Close();
    }

    public void Send(string msg)
    {
        _wss.Send(msg);
        OnLog?.Invoke(new Log { LogLevel = LogLevel.Info, Msg = $"WebSocket send msg:{msg}" });
    }

    public void SendByte(byte[] msg)
    {
        _wss.Send(msg);
        OnLog?.Invoke(new Log { LogLevel = LogLevel.Info, Msg = "WebSocket send msg: binary" });
    }
}